package com.xtremeprog;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 * User: denny
 * Date: Feb 25, 2009
 * Time: 2:36:40 PM
 * To change this template use File | Settings | File Templates.
 */
public class Squirrel {
    public static final String OMMIT = "{[*]}";
    public static final String FETCH_PRE = "[{";
    public static final String FETCH_SUX = "}]";

    public static final String FETCH_FLAG = "{{{[[[]]]]}}}";


    public static List<Map<String, String>> extractWith(String pattern, String content, String ommitFlag, String fetchPre, String fetchSux) {
        if (content == null || content.trim().length() == 0) {
            return Collections.EMPTY_LIST;
        }
        if (pattern == null || pattern.trim().length() == 0) {
            return Collections.EMPTY_LIST;
        }
        pattern = pattern.trim();
        if (pattern.startsWith(ommitFlag) || pattern.endsWith(ommitFlag)) {
            throw new RuntimeException("pattern error.");
        }

        Object[] tList = buildTokenList(pattern, ommitFlag, fetchPre, fetchSux, FETCH_FLAG);
        List<String> pList = (List<String>) tList[0];
        List<String> pNameList = (List<String>) tList[1];

        int tokenCount = 0;
        for (String token : pList) {
            if (FETCH_FLAG.equals(token)) {
                tokenCount++;
            }
        }

        List<Map<String, String>> rt = new ArrayList<Map<String, String>>();
        int cursor = 0;

        out:
        while (cursor < content.length() - 1) {
            // -1 eat, 0, ommit, 1 fetch
            int stat = -1;
            List<String> row = new ArrayList<String>();
            for (int i = 0; i < pList.size(); i++) {
                String token = pList.get(i);
                if (ommitFlag.equals(token)) {
                    stat = 0;
                    continue;
                } else if (FETCH_FLAG.equals(token)) {
                    stat = 1;
                    continue;
                }
                int index = content.indexOf(token, cursor);
                if (index == -1) {
                    break out;
                } else {
                    switch (stat) {
                        case -1:
                            cursor = index + token.length();
                            break;
                        case 0:
                            cursor = index + token.length();
                            break;
                        case 1:
                            row.add(content.substring(cursor, index));
                            cursor = index + token.length();
                            stat = -1;
                            break;
                    }
                }
            }

            if (row.size() == tokenCount) {
                Map<String, String> prow = new HashMap<String, String>(row.size());
                for (int i = 0; i < row.size(); i++) {
                    String value = row.get(i);
                    prow.put(pNameList.get(i), value);
                }
                rt.add(prow);
            } else {
                break;
            }
        }


        return rt;
    }


    public static List<Map<String, String>> extract(String pattern, String content) {
        return extractWith(pattern, content, OMMIT, FETCH_PRE, FETCH_SUX);
    }

    /**
     * @param pattern
     * @return object[0] List<String> tokens
     *         object[1] List<String> parameter names
     */
    private static Object[] buildTokenList(String pattern, String ommitFlag, String fetchPre, String fetchSux, String fetchFlag) {
        List<String> tokens = new ArrayList<String>();
        List<String> parameterNames = new ArrayList<String>();
        int cursor = 0;
        do {
            int ommitIndex = pattern.indexOf(ommitFlag, cursor);
            int fetchIndex = pattern.indexOf(fetchPre, cursor);
            if (ommitIndex == -1 && fetchIndex == -1) {
                tokens.add(pattern.substring(cursor));
                return new Object[]{tokens, parameterNames};
            }

            if (ommitIndex != -1 && fetchIndex != -1) {
                if (ommitIndex < fetchIndex) {
                    tokens.add(pattern.substring(cursor, ommitIndex));
                    tokens.add(ommitFlag);
                    cursor = ommitIndex + ommitFlag.length();
                } else {
                    tokens.add(pattern.substring(cursor, fetchIndex));
                    tokens.add(fetchFlag);
                    int fetchSuxIndex = pattern.indexOf(fetchSux, fetchIndex + fetchPre.length());
                    String parameterName = pattern.substring(fetchIndex + fetchPre.length(), fetchSuxIndex);
                    parameterNames.add(parameterName);
                    cursor = fetchSuxIndex + fetchSux.length();
                }
            } else {

                if (ommitIndex == -1) {
                    tokens.add(pattern.substring(cursor, fetchIndex));
                    tokens.add(fetchFlag);
                    int fetchSuxIndex = pattern.indexOf(fetchSux, fetchIndex + fetchPre.length());
                    String parameterName = pattern.substring(fetchIndex + fetchPre.length(), fetchSuxIndex);
                    parameterNames.add(parameterName);
                    cursor = fetchSuxIndex + fetchSux.length();
                } else {
                    tokens.add(pattern.substring(cursor, ommitIndex));
                    tokens.add(ommitFlag);
                    cursor = ommitIndex + ommitFlag.length();
                }
            }

        } while (true);
    }

}
